package main

import (
	"encoding/json"
	"mime"
	"net/http"
	"net/url"
	"path"
	"strings"
	"time"

	library "../../library"
	HTTP "../../library/http"
	"../../library/httplib/file"
	protocol "../../library/httplib/protocol"
	Key "../../library/key"
)

// FileDatabaseTable 数据库表
type FileDatabaseTable struct {
	// 主数据信息
	Address  string `json:"地址"`
	Headline string `json:"标题"`
	Digest   string `json:"摘要"`
	// 操作事件
	Public string `json:"公开"`
	// Delete string `json:"删除"`
	// 附加数据信息
	Time  string `json:"时间"`
	Types string `json:"类型"`
}

// FileDatabase 数据库
type FileDatabase struct {
	*HTTP.HTTP
	// 数据库参数
	FilePath      string     // 本地文件储存路径
	FileDB        library.DB // 文件数据库
	FileTableName string     // 文件数据表名
	// 路由参数
	Path     string   // 通用前戳
	UserKey  *Key.Key // 用户管理
	CacheKey *Key.Key // 缓存Key
}

// New 初始化
func (H *FileDatabase) New() (*FileDatabase, error) {
	// 初始化文件数据库
	_, err := H.FileDB.GetDB().Exec(`
			CREATE TABLE IF NOT EXISTS  [` + H.FileTableName + `] (
				"ID"	INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
				"Address"	TEXT NOT NULL UNIQUE,
				"Headline"	TEXT,
				"Digest"	TEXT,
				"Public" TEXT,
				"Delete" TEXT,
				"Time"	TEXT,
				"Types"	TEXT
			);`)
	if err != nil {
		return nil, err
	}
	// 数据库 DB
	Filedb := H.FileDB.GetDB()
	// !-------------------------------------------------!
	// * 数据json对应表
	MappingTable := make(map[string]string)
	// ? 映射数据
	MappingTable["标题"] = "Headline"
	MappingTable["摘要"] = "Digest"
	MappingTable["时间"] = "Time"
	MappingTable["类型"] = "Types"
	// !-------------------------------------------------!
	// * 统一设置
	// ? 文件缓存设置
	FileCache, _ := file.NewCache(H.FilePath, 30)
	// ? 公用路由
	AddPOST := func(Path string, Processor func(w http.ResponseWriter, r *http.Request, v map[string]interface{})) {
		POST := &protocol.Protocol{
			Path:         H.Path + Path,
			ProtocolType: "POST",
			// 处理过程
			Processor: Processor,
		}
		Handle := POST.Routing()
		Handle.CrossDomain = true
		H.Handle[Handle] = POST
	}
	// ? 管理员路由
	AddUserPOST := func(Path string, Processor func(w http.ResponseWriter, r *http.Request, v map[string]interface{})) {
		POST := &protocol.Protocol{
			Path:         H.Path + Path,
			ProtocolType: "POST",
			Key:          H.UserKey,
			UsingKey:     true,
			// 处理过程
			Processor: Processor,
		}
		Handle := POST.Routing()
		Handle.CrossDomain = true
		H.Handle[Handle] = POST
	}
	// * 查询用SQL
	SQLLineCache := `select Address,Headline,Digest,Public,Time,Types from ` + H.FileTableName + `  where "Public"='false' and "Delete"='false' order by ID desc limit ?*10,10;`
	SQLLineUser := `select Address,Headline,Digest,Public,Time,Types from ` + H.FileTableName + `  where "Delete"='false' order by ID desc limit ?*10,10;`
	SQLCountCache := "select count(*) from " + H.FileTableName + ` where "Delete"='false' and "Public"='false';`
	SQLCountUser := "select count(*) from " + H.FileTableName + ` where "Delete"='false';`
	SQLDelete := "update " + H.FileTableName + " set 'Delete'=? where Address=?"
	SQLPublic := "update " + H.FileTableName + " set 'Public'=? where Address=?"
	SQLWrite := "update `" + H.FileTableName + "` set `Time`=? where `Address`=? and `Delete`='false'"
	// ?-------------------- 公用路由 --------------------?
	// * Line 得到数据列
	AddPOST("/Line", func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
		// * 返回数据
		json := jsonError{}
		defer json.Submit(w)
		// * 判断用户参数
		if _, ok := v["line"]; !ok {
			json.Error = "参数异常"
			return
		}
		// * 判断用户访问类型
		SQL := ""
		if _, ok := H.CacheKey.IfKey(v, "Key"); !ok {
			if _, ok := H.UserKey.IfKey(v, "Key"); !ok {
				json.Error = "异常访问Key"
				return
			}
			SQL = SQLLineUser
		} else {
			SQL = SQLLineCache
		}
		// * 查询
		rows, err := Filedb.Query(SQL, v["line"])
		if err != nil {
			json.Error = err.Error()
			return
		}
		defer rows.Close() // 关闭
		// * 获得结果
		var Data []FileDatabaseTable
		for rows.Next() {
			// 数据结构
			data := FileDatabaseTable{}
			// 读取数据
			err := rows.Scan(&data.Address, &data.Headline, &data.Digest, &data.Public, &data.Time, &data.Types)
			if err != nil {
				json.Error += err.Error()
				continue
			}
			Data = append(Data, data)
		}
		json.Data = Data
	})
	// * Count 得到数量
	AddPOST("/Count", func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
		// * 返回数据
		json := jsonError{}
		defer json.Submit(w)
		// * 判断用户访问类型
		SQL := ""
		if _, ok := H.CacheKey.IfKey(v, "Key"); !ok {
			if _, ok := H.UserKey.IfKey(v, "Key"); !ok {
				json.Error = "异常访问Key"
				return
			}
			SQL = SQLCountUser
		} else {
			SQL = SQLCountCache
		}
		// * 得到数据
		err = Filedb.QueryRow(SQL).Scan(&json.Data)
		if err != nil {
			json.Error = err.Error()
		}
	})
	// ?------------------- 管理员路由 -------------------?
	// * GetModify 得到修改目标
	AddUserPOST("/GetModify", func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
		// * 返回数据
		json := jsonError{}
		defer json.Submit(w)
		// * 修改
		// * 得到文章标志
		var Address string
		if value, ok := v["Address"]; ok {
			if address, ok := value.(string); ok {
				Address = address
			} else {
				json.Error = "参数错误"
				return
			}
		} else {
			json.Error = "参数错误"
			return
		}
		// * 数据结构
		data := FileDatabaseTable{}
		// * 得到数据
		err = Filedb.QueryRow("select Address,Headline,Digest,Public,Time,Types from "+H.FileTableName+" where `Address`=? and `Delete`='false';", Address).Scan(&data.Address, &data.Headline, &data.Digest, &data.Public, &data.Time, &data.Types)
		if err != nil {
			json.Error = err.Error()
		}
		json.Data = data
	})
	// * Modify 修改数据
	AddUserPOST("/Modify", func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
		// * 返回数据
		json := jsonError{}
		defer json.Submit(w)
		// * 修改
		// * 得到文章标志
		var Address string
		if value, ok := v["Address"]; ok {
			if address, ok := value.(string); ok {
				Address = address
			} else {
				json.Error = "参数错误"
				return
			}
		} else {
			json.Error = "参数错误"
			return
		}
		// * 处理输入数据
		var SQL string
		var NewData []interface{}
		if value, ok := v["Data"]; ok {
			if value, ok := value.(map[string]interface{}); ok {
				for val, data := range value {
					// * 判断参数映射
					if val, ok = MappingTable[val]; !ok {
						json.Error = "异常参数"
						return
					}
					// * 构建查询语句
					NewData = append(NewData, data)
					SQL += val + "=?,"
				}
			}
		}
		// * 删除末尾
		if len(SQL) > 0 {
			SQL = SQL[:len(SQL)-1]
		}
		// * 构建查询目标
		NewData = append(NewData, Address)
		// * 处理数据库
		stmt, err := Filedb.Prepare("update " + H.FileTableName + " set " + SQL + " where Address=?")
		if err != nil {
			json.Error = "数据库查询失败: " + err.Error()
			return
		}
		defer stmt.Close()
		// * 修改数据
		if rs, err := stmt.Exec(NewData...); err != nil {
			json.Error = "数据库记录不存在: " + err.Error()
		} else {
			json.Data, _ = rs.RowsAffected()
		}
	})
	// * Delete 删除数据
	AddUserPOST("/Delete", func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
		// * 返回数据
		json := jsonError{}
		defer json.Submit(w)
		// * 得到文章标志
		var Address string
		if value, ok := v["Address"]; ok {
			if address, ok := value.(string); ok {
				Address = address
			} else {
				w.Write([]byte("参数错误"))
				return
			}
		} else {
			w.Write([]byte("参数错误"))
			return
		}
		// * 处理状态参数
		if value, ok := v["Status"]; ok {
			if status, ok := value.(string); ok {
				stmt, err := Filedb.Prepare(SQLDelete)
				if err != nil {
					w.Write([]byte("数据库查询失败: " + err.Error()))
					return
				}
				defer stmt.Close()
				// * 修改数据
				if rs, err := stmt.Exec(status, Address); err != nil {
					w.Write([]byte("数据库记录不存在: " + err.Error()))
				} else {
					_, _ = rs.RowsAffected()
					w.Write([]byte("Ok"))
				}
			} else {
				w.Write([]byte("参数错误"))
				return
			}
		} else {
			w.Write([]byte("参数错误"))
			return
		}
	})
	// * Public 隐藏数据
	AddUserPOST("/Public", func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
		// * 返回数据
		json := jsonError{}
		defer json.Submit(w)
		// * 得到文章标志
		var Address string
		if value, ok := v["Address"]; ok {
			if address, ok := value.(string); ok {
				Address = address
			} else {
				json.Error = "参数错误"
				return
			}
		} else {
			json.Error = "参数错误"
			return
		}
		// * 处理状态参数
		if value, ok := v["Status"]; ok {
			if status, ok := value.(string); ok {
				stmt, err := Filedb.Prepare(SQLPublic)
				if err != nil {
					json.Error = "数据库查询失败: " + err.Error()
					return
				}
				defer stmt.Close()
				// * 修改数据
				if rs, err := stmt.Exec(status, Address); err != nil {
					json.Error = "数据库记录不存在: " + err.Error()
				} else {
					_, _ = rs.RowsAffected()
					json.Data = "Ok"
				}
			} else {
				json.Error = "参数类型错误:string[true/false]"
				return
			}
		} else {
			json.Error = "参数错误"
			return
		}
	})
	// ?-------------------- 文件路由 --------------------?
	// * Read 读文件
	{
		GET := &protocol.Protocol{
			Path:         H.Path + `/Read/(.*?)`,
			RegExp:       true,
			ProtocolType: "GET",
			Key:          H.CacheKey,
			UsingKey:     true,
			// 处理过程
			Processor: func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
				// * 打开文件
				file, _ := url.PathUnescape(r.URL.String())
				// * 去除参数
				N := strings.Index(file, "?")
				if N != -1 {
					file = (file)[:N]
				}
				// * 得到文件名
				N = strings.LastIndex(file, "/")
				if N != -1 {
					file = file[N+1:]
				}
				// * 设置返回头
				ctype := mime.TypeByExtension(path.Ext(file))
				w.Header().Set("Content-Type", ctype)
				// * 读文件
				if data, err := FileCache.Read(file); err == nil {
					w.WriteHeader(http.StatusOK)
					w.Write(data)
				} else {
					// * 打开文件
					if item, err := FileCache.Open(file); err == nil {
						w.WriteHeader(http.StatusOK)
						w.Write(item.Data)
					} else {
						w.WriteHeader(http.StatusNotFound)
					}
				}
			},
		}
		Handle := GET.Routing()
		Handle.CrossDomain = true
		H.Handle[Handle] = GET
	}
	// * Write 写文件
	AddUserPOST("/Write", func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
		// * 返回数据
		json := jsonError{}
		defer json.Submit(w)
		// * 得到文件路径
		file := ""
		if value, ok := v["File"]; ok {
			if file, ok = value.(string); !ok {
				json.Error = "参数错误"
				return
			}
		}
		// * 验证参数
		result, err := Filedb.Exec(SQLWrite, time.Now().Format("2006年01月02日"), file)
		if err != nil {
			json.Error = "更新数据库失败:" + err.Error()
			return
		}
		_, _ = result.RowsAffected()
		// * 写文件
		if value, ok := v["Data"]; ok {
			var data string
			if data, ok = value.(string); !ok {
				json.Error = "参数错误"
				return
			}
			// * 写数据
			if FileCache.Write(file, []byte(data)) == nil {
				w.WriteHeader(http.StatusOK)
				json.Data = "Ok"
			} else {
				// * 打开文件
				if item, err := FileCache.Open(file); err == nil {
					// * 更新数据
					item.Data = []byte(data)
					item.Sync = true
					// * 设置返回
					json.Data = "Ok"
				} else {
					json.Error = "文件不存在"
				}
				return
			}
		}
	})
	return H, nil
}

// * 错误处理对象
type jsonError struct {
	Data  interface{}
	Error string
}

func (Json *jsonError) Submit(w http.ResponseWriter) {
	// 转换 json
	data, err := json.Marshal(*Json)
	if err != nil {
		return
	}
	// 发送到前端
	w.Write(data)
}
